#!/usr/bin/env python

"""
__description__ = 'Program to check if your computer is likely to be vulnerable to exploitable constant Read-Write-Execute (RWX) addresses (AVs vulnerability)'
__author__ = 'Udi Yavo, Tomer Bitton'
__company__ = 'enSilo'
__version__ = '1.0'
__date__ = '2015/12/07'

Source code put in public domain by Udi Yavo and Tomer Bitton, no Copyright
http://breakingmalware.com/
http://ensilo.com/
Use at your own risk
"""

from winappdbg import System
from winappdbg import win32, Process, HexDump
import struct
import os.path
import os
import sys

class RuntimeCodeInfo:
	def __init__(self, base, size, code):
		self.base = base
		self.size = size
		self.processes = {}
		self.code = code
		self.count = 0

	def add_process(self, process, pid):
		self.processes.setdefault(process, []).append(pid)
		# self.processes.add(process)
		self.count += 1

def scan_process_memory( process, runtime_code_dict ):
    # Get the process memory map.
	memoryMap = process.get_memory_map()

	for mbi in memoryMap:

		# State (free or allocated).
		if mbi.State != win32.MEM_COMMIT and not (mbi.Type == win32.MEM_MAPPED or mbi.Type == win32.MEM_PRIVATE):
			continue

		if mbi.Protect & win32.PAGE_EXECUTE_READWRITE:
			if process.get_module_at_address(mbi.BaseAddress) is None:
				runtime_code = runtime_code_dict.setdefault("0x%x-0x%x" % (mbi.BaseAddress,mbi.BaseAddress + mbi.RegionSize), RuntimeCodeInfo(mbi.BaseAddress, mbi.RegionSize, process.read(mbi.BaseAddress, mbi.RegionSize) ))
				runtime_code.add_process("%s" % (os.path.basename(process.get_filename())), process.get_pid())
							

# RELEVANT_PROCSS_LIST = set(["outlook.exe","chrome.exe", "iexplore.exe", "firefox.exe", "AcroRd32.exe", "explorer.exe"])
RELEVANT_PROCSS_LIST = set(["chrome.exe", "iexplore.exe", "firefox.exe"])
# Now we can enumerate the running processes.
System.request_debug_privileges()
def scan_processes():
	runtime_code_dict = {}
	# Create a system snaphot.
	number_of_scanned_processes = 0
	system = System()
	for process in system:
		if process.get_filename() and os.path.basename(process.get_filename()).lower() in RELEVANT_PROCSS_LIST:
			try:
				scan_process_memory(process, runtime_code_dict)
				number_of_scanned_processes += 1
			except:
				pass
	return runtime_code_dict, number_of_scanned_processes
print "Please make sure at least two browser tabs are open before running the tool."
print ""
os.system('pause')
print "\nScanning...\n"
first_scan, number_of_scanned_processes = scan_processes()

if number_of_scanned_processes == 0:
	print "No open browsers were found. Exiting..."
	sys.exit(0)

print "Close all browsers and open at least two new tabs.\n"
os.system('pause')
print "\nScanning to determine results...\n"
second_scan, number_of_scanned_processes2 = scan_processes()
while number_of_scanned_processes2 == 0:
	print "No open browsers were found."
	print "Close all browsers and open at least two new tabs.\n"
	os.system('pause')
	print "\nScanning to determine results...\n"
	second_scan, number_of_scanned_processes2 = scan_processes()	

res = filter(lambda x: x[0] in second_scan, sorted(second_scan.iteritems(),key=lambda x: x[0]))
res = filter(lambda x: x[1].base < 0x50000 or x[1].count>1, res)
if res:
	print "Your computer is likely to be vulnerable to exploitable constant\nRead-Write-Execute (RWX) addresses.\n"
	print "Details:"
	for base, code in res:	
		print "\tBase Address: 0x%x, Size: 0x%x" % (code.base, code.size)
		print "\tAffected Processes:"
		for proc_name, pids in sorted(code.processes.iteritems(), key=lambda x: x[0]):
			print "\t\t%s(%s)" % (proc_name, ", ".join(map(str, pids)))
		print "---------------------------------------------"
	print ""
else:
	print "Most likely your computer is not vulnerable to exploitable constant\nRead-Write-Execute (RWX) addresses.\n"

print "For further details, see: http://blog.ensilo.com/topic/research\n"
os.system('pause')